<template>
  <div class="desktop_frame" v-contextmenu:contextmenu @mousemove="mouse_move_record" @mousedown="mouse_down_record"
    @mouseup="mouse_up_record">
    <v-contextmenu ref="contextmenu" @show="menu_show_callback" @hide="menu_hide_callback">
      <v-contextmenu-item>打开</v-contextmenu-item>
      <v-contextmenu-submenu title="新建">
        <v-contextmenu-item @click="newDir">文件夹</v-contextmenu-item>
        <v-contextmenu-item>文本文件</v-contextmenu-item>
        <v-contextmenu-submenu title="代码">
          <v-contextmenu-item @click="newFile('.java')">Java</v-contextmenu-item>
          <v-contextmenu-item @click="newFile('.js')">Js</v-contextmenu-item>
          <v-contextmenu-item @click="newFile('.py')">Python</v-contextmenu-item>
          <v-contextmenu-item @click="newFile('.cpp')">C++</v-contextmenu-item>
          <v-contextmenu-item @click="newFile('.c')">C</v-contextmenu-item>
          <v-contextmenu-item @click="newFile('.h')">h</v-contextmenu-item>
        </v-contextmenu-submenu>
      </v-contextmenu-submenu>
      <v-contextmenu-item @click="__flush">刷新</v-contextmenu-item>
      <v-contextmenu-item @click="sortFile">一键整理</v-contextmenu-item>
      <v-contextmenu-submenu title="下载">
        <v-contextmenu-item @click="downloadFile">下载至本地</v-contextmenu-item>
      </v-contextmenu-submenu>
      <v-contextmenu-item @click="deleteFile">删除</v-contextmenu-item>
    </v-contextmenu>
    <el-row>
      <el-col :span="2" :offset="0" v-for="(v, i) in desk_files[0]" :key="v ? v.fileId : i">
        <FileItem :file="v" :mouse="mouse"></FileItem>
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="2" :offset="0" v-for="(v, i) in desk_files[1]" :key="v ? v.fileId : i">
        <FileItem :file="v" :mouse="mouse"></FileItem>
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="2" :offset="0" v-for="(v, i) in desk_files[2]" :key="v ? v.fileId : i">
        <FileItem :file="v" :mouse="mouse"></FileItem>
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="2" :offset="0" v-for="(v, i) in desk_files[3]" :key="v ? v.fileId : i">
        <FileItem :file="v" :mouse="mouse"></FileItem>
      </el-col>
    </el-row>

  </div>
</template>

<script>
import { mapState } from "vuex";
import FileItem from "./FileItem.vue";
export default {
  name: "Desktop",
  data() {
    return {
      desk_files: new Array(4),
      isUploading: false,
      hover_file: null,
      hover_file_now: null,
      mouse: {
        x: 0,
        y: 0,
        pre_x: 0,
        pre_y: 0,
        down_x: 0,
        down_y: 0,
        up_x: 0,
        up_y: 0,
        is_up: true,
        file: null,
      },
    };
  },
  components: {
    FileItem,
  },
  mounted() {
    this.__init();
  },
  destroyed() {
    window.removeEventListener("drop", this.uploadFile);
    window.removeEventListener("dragleave", this.dropelse);
    window.removeEventListener("dragenter", this.dropelse);
    window.removeEventListener("dragout", this.dropelse);
  },
  computed: {
    ...mapState("userAbout", ["token", "user"]),
    position() {
      // 获取空余位置
      // console.log(this.desk_files)
      for (let i = 0; i < this.desk_files.length; i++) {
        if (this.desk_files[i] == null || this.desk_files[i] == undefined)
          continue;
        for (let j = 0; j < this.desk_files[i].length; j++)
          if (this.desk_files[i][j] == null) return { x: i, y: j };
      }
      return null;
    },
  },
  methods: {
    __init() {
      this.__flush();
      this.__event_listen();
    },
    __event_listen() {
      this.$pubsub.subscribe("insert_desk_file", this.insert_file);
      this.$pubsub.subscribe("delete_desk_file", this.delete_file);
      this.$pubsub.subscribe("update_hover_file", this.update_hover_file);
      // 监视文件拖动
      window.addEventListener("drop", this.uploadFile, false);
      window.addEventListener("dragleave", this.dropelse);
      window.addEventListener("dragenter", this.dropelse);
      window.addEventListener("dragover", this.dropelse);
    },
    __flush() {
      this.$basicAxios(this.$ms.get_desk(this.token), (resp) => {
        const desk_files = this.resolve(resp.data.data);
        this.desk_files = desk_files;
      })
    },
    resolve(arr) {
      // 解析文件
      const data = this.initData();
      for (let i = 0; i < arr.length; i++) {
        //console.log(i)
        data[arr[i].x][arr[i].y] = arr[i];
      }
      // console.log(data);
      return data;
    },
    initData() {
      // 4*12的数组
      const data = new Array();
      for (let i = 0; i < 4; i++) {
        const data1 = new Array();
        for (let i = 0; i < 12; i++) data1.push(null);
        data.push(data1);
      }

      return data;
    },
    newFile(suffix) {
      if (this.position == null) {
        this.notify("warn", "[ 提示 ] 你的桌面已满,请先整理桌面");
        return;
      }
      // 获取父文件夹id
      const parId = this.user.userId;
      let { x, y } = this.position;
      this.$basicAxios(this.$ms.create_desk_file(parId, x, y, this.token, suffix), (resp) => {
        const file = { ...resp.data.data };
        this.$set(this.desk_files[x], y, file);
      })
    },
    newDir() {
      if (this.position == null) {
        this.notify("warn", "[ 提示 ] 你的桌面已满,请先整理桌面");
        return;
      }
      const par_id = this.user.userId;
      let { x, y } = this.position;
      this.$basicAxios(this.$ms.create_desk_dir(par_id, x, y, this.token), (resp) => {
        const file = { ...resp.data.data };
        this.$set(this.desk_files[x], y, file);
      })
    },
    name_focus() {
      this.$pubsub.publish(`focusname:${x}-${y}`);
    },
    insert_file(name, file) {
      this.$set(this.desk_files[file.x], file.y, file);
    },
    delete_file(name, file) {
      if (
        file.x == null ||
        file.x == undefined ||
        file.y == null ||
        file.y == undefined
      ) {
        this.desk_files.forEach((e) => {
          e.forEach((e1) => {
            if (e1 && e1.fileId == file.fileId) {
              this.$set(this.desk_files[e1.x], e1.y, null);
              return;
            }
          });
        });
        return;
      }
      this.$set(this.desk_files[file.x], file.y, null);
    },
    uploadFile(e) {
      e.stopPropagation();
      e.preventDefault();
      if (
        e.dataTransfer.files == undefined ||
        e.dataTransfer.files == null ||
        e.dataTransfer.files.length == 0
      ) {
        this.notify("error", "[ 错误 ] 请重新拖拽文件");
      }
      if (this.isUploading) {
        // 已经有文件在上传
        this.notify("warn", "[ 提醒 ] 请等待上一个文件上传完毕");
        return;
      }
      //console.log(e);
      if (this.position == null) {
        this.notify("warn", "[ 提醒 ] 你的桌面已满,请先整理桌面");
      } else {
        this.isUploading = true;
        const file = e.dataTransfer.files[0];
        const fileName = file.name.replace(/\#/g, "%23");
        const x = this.position.x;
        const y = this.position.y;
        const formdata = new FormData();
        formdata.append("mtf", file);
        this.$basicAxios(this.$ms.upload_file(this.user.userId, fileName, x, y, formdata, this.token), (resp) => {
          this.$set(this.desk_files[x], y, resp.data.data);
          this.notify("success", "[ 成功 ] 文件上传成功");
        }, (resp) => {
          if (resp.data.code == 501) {
            this.file_upload_select(file, formdata);
          } else this.notify("error", resp.data.msg);
        }).then(() => {
          this.isUploading = false;
        }, () => { this.isUploading = false; })
      }
    },
    dropelse(e) {
      e.stopPropagation();
      e.preventDefault();
    },
    file_upload_select(fileId, mtf) {
      this.$confirm("该文件夹下已存在相同文件", "覆盖还是合并", {
        confirmButtonText: "合并",
        cancelButtonText: "覆盖",
        distinguishCancelAndClose: true,
        type: "waring",
      })
        .then(() => {
          this.$basicAxios(this.$ms.upload_file_after(fileId, false, mtf, this.token)).then(() => { this.isUploading = false }, () => { this.isUploading = false })
        })
        .catch((action) => {
          if (action != "close") {
            this.$basicAxios(this.$ms.upload_file_after(fileId, true, mtf, this.token),).then(() => { this.isUploading = false }, () => { this.isUploading = false })
          }
        });
    },
    update_hover_file(name, file) {
      this.hover_file = file;
    },
    deleteFile() {
      if (this.hover_file_now) {
        const file = this.hover_file_now;
        this.hover_file_now = null;
        // 文件删除
        this.delete_file(null, file);
        // 网络异步删除
        let p;
        if (file.fileType == 1) {
          p = this.$ms.delete_file(file.fileId, this.token);
        } else {
          p = this.$ms.delete_dir(file.fileId, this.token);
        }
        p.then(
          (resp) => {
            if (resp.data.code != 200) {
              this.notify("error", resp.data.msg);
            } else {
              // 文件删除成功
              console.log(resp.data.data);
            }
          },
          (resp) => {
            this.notify("error", `[ ${resp.name} ] ${resp.message}`);
          }
        );
      }
    },
    menu_show_callback() {
      if (this.hover_file) this.hover_file_now = this.hover_file;
    },
    menu_hide_callback() {
      this.hover_file_now = null;
    },
    mouse_move_record(event) {
      const width = document.body.clientWidth;
      const height = document.body.clientHeight;
      this.mouse.pre_x = this.mouse.x;
      this.mouse.pre_y = this.mouse.y;
      this.mouse.x = event.clientX;
      this.mouse.y = event.clientY;
      if (
        event.clientX < 0.05 * width ||
        event.clientX > width * 0.98 ||
        event.clientY < 0.1 * height ||
        event.clientY > document.body.clientHeight * 0.82
      ) {
        // 超出屏幕
        // 这里进行位置移动
        this.mouse_up_record(event);
        return;
      }
      //console.log(event)
    },
    mouse_down_record(event) {
      this.mouse.is_up = false;
      this.mouse.down_x = event.clientX;
      this.mouse.down_y = event.clientY;
    },
    mouse_up_record(event) {
      if (this.mouse.file != null) {
        // 进行坐标的定位
        const width = document.body.clientWidth;
        const height = document.body.clientHeight;
        const x = event.clientX;
        const y = event.clientY;
        // 获得中心点偏移量
        let dir_x;
        let dir_y;
        if (x < this.mouse.down_x) dir_x = -1;
        else dir_x = 1;
        if (y < this.mouse.down_y) dir_y = -1;
        else dir_y = 1;
        let dy =
          dir_x * parseInt(Math.abs((x - this.mouse.down_x) / (width / 12)));
        dy +=
          Math.abs(x - this.mouse.down_x) % (width / 12) > width / 24
            ? dir_x
            : 0;
        let dx =
          dir_y *
          parseInt(Math.abs((y - this.mouse.down_y) / ((height * 0.85) / 4)));
        dx +=
          Math.abs(y - this.mouse.down_y) % ((height * 0.85) / 4) >
            (height * 0.85) / 8
            ? dir_y
            : 0;
        if (dx != 0 || dy != 0) {
          // 进行图标重定位
          let to_x;
          let to_y;
          if (this.mouse.file.x + dx < 0) {
            to_x = 0;
          } else if (this.mouse.file.x + dx > 3) {
            to_x = 3;
          } else {
            to_x = this.mouse.file.x + dx;
          }
          if (this.mouse.file.y + dy < 0) {
            to_y = 0;
          } else if (this.mouse.file.y + dy > 11) {
            to_y = 11;
          } else {
            to_y = this.mouse.file.y + dy;
          }
          if (this.desk_files[to_x][to_y] == null) {
            this.$set(this.desk_files[to_x], to_y, this.mouse.file);
            this.$set(
              this.desk_files[this.mouse.file.x],
              this.mouse.file.y,
              null
            );
            //this.move_file()
            this.mouse.file.x = to_x;
            this.mouse.file.y = to_y;
            this.move_file(this.mouse.file);
          } else {
            // 进行交换
            const file = this.desk_files[to_x][to_y];
            this.$set(this.desk_files[to_x], to_y, this.mouse.file);
            this.$set(
              this.desk_files[this.mouse.file.x],
              this.mouse.file.y,
              file
            );
            file.x = this.mouse.file.x;
            file.y = this.mouse.file.y;
            this.mouse.file.x = to_x;
            this.mouse.file.y = to_y;
          }
        }
      }
      this.mouse.is_up = true;
      this.mouse.file = null;
      this.mouse.up_x = event.clientX;
      this.mouse.up_y = event.cleintY;
    },
    move_file(file) {
      this.$ms.move_file(file.fileId, file.x, file.y, this.token).then(
        (resp) => {
          if (resp.data.code != 200) {
            this.notify("error", resp.data.msg);
          }
        },
        (resp) => {
          this.notify("error", `[ ${resp.name} ] ${resp.message}`);
        }
      );
    },
    downloadFile() {
      if (this.hover_file_now) {
        const file = this.hover_file_now;
        this.hover_file_now = null;
        this.$ms.download_file(file.fileId, this.token).then(
          (resp) => {
            if (resp.data.code) this.notify('error', resp.data.msg)
            else this.save_file_disk(file, resp);
          },
          (resp) => {
            this.notify("error", `[ ${resp.name} ] ${resp.message}`);
          }
        );
      }
    },
    save_file_disk(file, resp) {
      const content = new Blob([resp.data]);
      const elink = document.createElement("a");
      elink.download = file.fileName;
      elink.style.display = "none";
      elink.href = URL.createObjectURL(content);
      document.body.appendChild(elink);
      elink.click();
      document.body.removeChild(elink);
      window.URL.revokeObjectURL(content);
    },
    sortFile() {
      this.$basicAxios(this.$ms.sortFile(this.token),()=>{this.__flush()})
    }
  },
};
</script>

<style scoped lang="less">
.desktop_frame {
  font-size: 12px;
  height: 100%;
  width: 100%;
  font-family: Hiragino Sans GB;
  overflow-x: hidden;
  overflow-y: hidden;
}

/deep/.el-row {
  width: 100%;
  height: 25%;
}

/deep/.el-col {
  height: 100%;
  /*position: absolute; /* 一定要用绝对定位 */
}
</style>